//
// maths.cpp for  in /home/goldbe_y//cpp/Maths/204param
//
// Made by yoni goldberg
// Login   <goldbe_y@epitech.net>
//
// Started on  Tue Mar 29 18:44:05 2011 yoni goldberg
// Last update Fri Apr 29 18:36:37 2011 leo faucon
//

#include "maths.hpp"
#include "convert.hpp"

Maths::Maths(double _a, double _b)
{
  a = _a;
  b = _b;
  c = 0;
  d = 1;
  min = -10;
  n = 20;
  borne_a = -4;
  borne_b = 4;
  option = false;
}

Maths::Maths(double _a, double _b, double _c, double _d)
{
  a = _a;
  b = _b;
  c = _c;
  d = _d;
  min = -10;
  n = 20;
  borne_a = -10;
  borne_b = 10;
  option = true;
}


Maths::~Maths()
{
}

double		Maths::calc(double val)
{
  double temp = (1. / (std::sqrt(2 * M_PI * d)));
  double tmp = -pow((val - c),2);

  tmp /= (2 * d);
  temp *= exp(tmp);
  return (temp);
}

double		Maths::calc2(double val)
{
  val *= val;
  return (exp(-val/2));
}

double		Maths::somme(bool gni)
{
  double	plop = 0;
  int		i = gni ? 1 : 0;

  while (i <= n - 1)
    {
      if (gni)
	plop += calc2(min + i * h);
      else
	plop += calc2(min + i * h + (h / 2));
      i++;
    }
  return plop;
}

void		Maths::loi()
{
  resultat = (simpson((b - c) / d) - simpson((a - c) / d));
}

double		Maths::simpson(double val)
{
  h = (val - min);
  h /= n;

  temp[0] = val - min;
  temp[0] /= (6 * n);
  temp[1] = calc2(min);
  temp[2] = calc2(val);
  temp[3] = 2 * somme(true);
  temp[4] = 4 * somme(false);
  temp[0] *= (temp[1] + temp[2] + temp[3] + temp[4]);
  temp[0] /= (sqrt(2*M_PI));
  return temp[0];
}

double		calc_aff(double y)
{
  double hauteur = y * 1000;
  double tmp = 550 - hauteur;
  return (tmp);
}

void	Maths::axes_courbe(SDL_opt * win, SDL_graph * graph, double i, int grad)
{
  win->position.x = 45;
  win->position.y = 560;
  int	x_grad = 50;
  while (i < (borne_b + 1))
    {
      if (i != 0)
	graph->ligne_graphVerticale(x_grad,540,10, graph->couleurs[12]);
      x_grad += grad;
      std::string str = var_to_string(i, 0);
      win->aff_texte(str, win->couleurJaune);
      win->position.x += grad;
      if (borne_b > 10)
	{
	  i += 3;
	  x_grad += (grad * 3);
	  win->position.x += (grad * 3);
	}
      i++;
    }
}

void		Maths::courbe(SDL_opt * win)
{
  int		grad = 500 / borne_b;
  double	i;
  double	x = 50;
  double	y = calc_aff(this->calc(borne_a));
  SDL_graph	graph(win->get_ecran());

  if (borne_a < 0)
    {
      grad = 500 / (borne_b + -borne_a);
      graph.ligne_graphVerticale(50 + (grad * -borne_a),50,500, graph.couleurs[12]);
    }
  else
    graph.ligne_graphVerticale(50,50,500, graph.couleurs[12]);
  graph.ligne_graphHorizontale(50, 550, 500, graph.couleurs[12]);
  (borne_a > 0) ? (i = 0) : (i = borne_a);
  axes_courbe(win, &graph, i, grad);
  i = borne_a;
  (borne_a > 0) ? (x += grad * borne_a) : (x = x);
  while (i < (borne_b - 0.1))
    {
      double save_y = y;
      i += 0.1;
      x += (grad * 0.1);
      y = this->calc(i);
      y = calc_aff(y);
      graph.ligne_graph(x - (grad * 0.1), save_y, x, y, graph.couleurs[14]);
    }
  win->position.x = 70;
  win->position.y = 600;
  std::string str = var_to_string(resultat, 3);
  std::ostringstream s;
  if (option)
    s << "Loi normale avec u = " << c << " , sigma carre = " << d
      << " : P(" << a <<" <= Z <= " << b << ") = " << str;
  else
    s << "Loi normale centree : P(" << a <<" <= Z <= " << b << ") = " << str;
  win->aff_texte(s.str(), win->couleurRouge);
  graph.actualiser();
  while (1)
    {
      int ret = graph.attendreTouche();
      if (ret == -1 || ret == SDLK_ESCAPE)
	break;
    }
}
